#include "soft_i2c.h"

// 软件模拟IIC

#define I2C_SPEED_KHZ 100  // I2C通信速度，单位为kHz
#define I2C_SPEED_US (1000 / I2C_SPEED_KHZ)  // 将速度转换为微秒

static void i2c_delay_us(uint32_t us) {
    uint16_t i = 0;  
    while(us --)
    {
        i = 9;
        while(i--) ;    
    }
}


// 初始化GPIO
void soft_i2c_init() 
{
    // 初始化时SCL和SDA都设置为高电平
    i2c_scl_high();
    i2c_sda_high();
}

// 发送起始位
static void i2c_start() 
{
    i2c_delay_us(10);  // 等待t_STO
    i2c_sda_high();
    i2c_delay_us(I2C_SPEED_US / 4);  // 等待t_SU_STA
    i2c_scl_high();
    i2c_delay_us(I2C_SPEED_US / 2);  // 等待t_SU_STA
    i2c_sda_low();
    i2c_delay_us(I2C_SPEED_US / 2);  // 等待t_SU_STA
    i2c_scl_low();
}

// 发送停止位
static void i2c_stop() 
{
    i2c_sda_low();
    i2c_delay_us(I2C_SPEED_US / 4);  // 等待t_BUF
    i2c_scl_high();
    i2c_delay_us(I2C_SPEED_US / 2);  // 等待t_SU_STO
    i2c_sda_high();
    i2c_delay_us(I2C_SPEED_US / 2);  // 等待t_STO
    i2c_delay_us(10);  // 等待t_STO
}

// 发送应答位
static void i2c_ack() 
{
    i2c_sda_low();
    i2c_delay_us(I2C_SPEED_US / 2);  // 等待t_SU_STO
    i2c_scl_high();
    i2c_delay_us(I2C_SPEED_US / 2);  // 等待t_SU_STO
    i2c_scl_low();
    i2c_delay_us(I2C_SPEED_US / 4);  // 等待t_SU_STO
    i2c_sda_high();
}

// 发送非应答位
static void i2c_nack() {
    i2c_sda_high();
    i2c_delay_us(I2C_SPEED_US / 2);  // 等待t_SU_STO
    i2c_scl_high();
    i2c_delay_us(I2C_SPEED_US / 2);  // 等待t_SU_STO
    i2c_scl_low();
}

// 等待应答
static uint8_t i2c_wait_ack() 
{
    uint8_t ack;
    i2c_sda_high();
    i2c_delay_us(I2C_SPEED_US / 4);  // 等待t_SU_STO
    i2c_scl_high();
    i2c_delay_us(I2C_SPEED_US / 4);  // 等待t_SU_STO
    ack = i2c_sda_read();
    i2c_delay_us(I2C_SPEED_US / 4);  // 等待t_SU_STO
    i2c_scl_low();
    return !ack;
}

// 发送一个字节数据
static void i2c_send_byte(uint8_t data) 
{
    uint8_t i;
    for (i = 0; i < 8; i++) {
        if (data & 0x80) {
            i2c_sda_high();
        } else {
            i2c_sda_low();
        }
        i2c_delay_us(I2C_SPEED_US / 2);  // 等待t_SU_STO
        i2c_scl_high();
        i2c_delay_us(I2C_SPEED_US / 2);  // 等待t_SU_STO
        i2c_scl_low();
        data <<= 1;
    }
}

// 读取一个字节数据
static uint8_t i2c_read_byte(uint8_t ack) 
{
    uint8_t i, data = 0;
    i2c_sda_high();
    for (i = 0; i < 8; i++) {
        i2c_delay_us(I2C_SPEED_US / 2);  // 等待t_SU_STO
        i2c_scl_high();
        data <<= 1;
        if (i2c_sda_read()) {
            data |= 0x01;
        }
        i2c_delay_us(I2C_SPEED_US / 2);  // 等待t_SU_STO
        i2c_scl_low();
    }
    if (ack) {
        i2c_ack();
    } else {
        i2c_nack();
    }
    return data;
}

// 写寄存器
uint8_t soft_i2c_write_register(uint8_t device_address, uint8_t register_address, uint8_t* data, int len) 
{
    int i;
    i2c_start();
    i2c_send_byte(device_address << 1);
    if (i2c_wait_ack()) 
    {
        i2c_send_byte(register_address);
        if (i2c_wait_ack() && len > 0) 
        {
            i2c_send_byte(data[0]);
            for(i = 1; i < len; i ++) 
            {
                if(!i2c_wait_ack())
                {
                    break;
                }
                i2c_send_byte(data[i]);
            }
        }
    }
    i2c_stop();
    if(i == len)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

// 读取寄存器
uint8_t soft_i2c_read_register(uint8_t device_address, uint8_t register_address, uint8_t* data, int len) 
{
    i2c_start();
    i2c_send_byte(device_address << 1);
    if (i2c_wait_ack()) 
    {
        i2c_send_byte(register_address);
        if (i2c_wait_ack()) 
        {
            i2c_start();
            i2c_send_byte((device_address << 1) | 0x01);
            if (i2c_wait_ack()) 
            {
                for(int i = 0; i < len; i ++) 
                {
                    data[i] = i2c_read_byte(i != (len - 1));
                }
            }
        }
        i2c_stop();
        return 0;
    }
    else
    {
        i2c_stop();
        return 1;
    }
}
